package com.ruoyi.common.filter;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ruoyi.common.utils.ip.RegionUtils;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.servlet.ServletUtil;

public class AntiVulnScanFilter implements Filter {
	
	private static final Logger logger = LoggerFactory.getLogger(AntiVulnScanFilter.class);
	
	public static final String BLACKLIST = "blacklist";
	
	private Set<String> blackList = new HashSet<>();
	
	private static final Cache<String,String> fifoCache = CacheUtil.newFIFOCache(50, 1800000);

	@Override
    public void init(FilterConfig filterConfig) throws ServletException {
		String blacklist = filterConfig.getInitParameter(BLACKLIST);
        if (StringUtils.isNotEmpty(blacklist)) {
            String[] url = blacklist.split(",");
            for (int i = 0; url != null && i < url.length; i++) {
            	blackList.add(url[i]);
            }
        }
    }

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;
		
		String ipAddr = getClientIp(req);
		String url = req.getRequestURI();
		String suffix = StringUtils.substringAfterLast(url, ".");
		
		if(fifoCache.containsKey(ipAddr)) {
			String cityInfo = fifoCache.get(ipAddr);
			logger.info("非法网络请求，访问时间:{}，客户端ip:{}，ip归属地:{}，请求地址:{}", DateUtil.now(), ipAddr, cityInfo, url);
			
			ServletUtil.write(res, "非法请求，已被系统拦截", "text/plain;charset=utf-8");
			return;
		}
		
		if(StringUtils.isBlank(suffix) || !blackList.contains(suffix)) {
			chain.doFilter(request, response);
		} else {
			String cityInfo = null;
			
			if(!fifoCache.containsKey(ipAddr)) {
				cityInfo = RegionUtils.getCityInfo(ipAddr);
				fifoCache.put(ipAddr, cityInfo);
			} else {
				cityInfo = fifoCache.get(ipAddr);
			}
			
			logger.info("非法网络请求，访问时间:{}，客户端ip:{}，ip归属地:{}，请求地址:{}", DateUtil.now(), ipAddr, cityInfo, url);
			
			ServletUtil.write(res, "非法请求，已被系统拦截", "text/plain;charset=utf-8");
		}
	}
	
	public String getClientIp(HttpServletRequest request) {
		return ServletUtil.getClientIP(request);
	}
	
	@Override
    public void destroy() {

    }
	
}
